package com.waves.task.service.impl;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.BooleanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.waves.core.constant.TimeConstant;
import com.waves.core.constant.redis.TaskRedisKey;
import com.waves.core.constant.redis.UserRedisKey;
import com.waves.core.service.LockService;
import com.waves.core.support.EntityOperations;
import com.waves.core.utils.*;
import com.waves.core.web.domain.R;
import com.waves.core.web.domain.TableDataInfo;
import com.waves.core.web.domain.entities.User;
import com.waves.pay.domain.dto.AlipayDto;
import com.waves.pay.service.AlipayService;
import com.waves.task.dao.TaskCommentDao;
import com.waves.task.dao.TaskCopyDao;
import com.waves.task.dao.TaskDao;
import com.waves.task.dao.TaskReceiveDao;
import com.waves.task.domain.dto.TaskDTO;
import com.waves.task.domain.dto.TaskPageDTO;
import com.waves.task.domain.entity.Task;
import com.waves.task.domain.entity.TaskComment;
import com.waves.task.domain.entity.TaskCopy;
import com.waves.task.domain.entity.TaskReceive;
import com.waves.task.domain.enums.*;
import com.waves.task.domain.pojo.GeoEventPOJO;
import com.waves.task.domain.pojo.TaskRedisSetPOJO;
import com.waves.task.domain.vo.TaskReceiveVO;
import com.waves.task.domain.vo.TaskVO;
import com.waves.task.event.TaskRedisSetEvent;
import com.waves.task.event.TaskUserGeoEvent;
import com.waves.task.mapper.TaskMapper;
import com.waves.task.service.TaskService;
import com.waves.task.strategy.receive.AbstractReceiveStrategy;
import com.waves.task.strategy.receive.ReceiveFactory;
import com.waves.task.strategy.task.AbstractTaskStrategy;
import com.waves.task.strategy.task.TaskFactory;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * 任务表;(task)表服务实现类
 *
 * @author : dlw
 * @date : 2024-9-18
 */
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@Slf4j
public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements TaskService {

    private final TaskDao taskDao;

    private final TaskReceiveDao taskReceiveDao;

    private final TaskCommentDao taskCommentDao;

    private final TaskCopyDao taskCopyDao;

    private final AlipayService alipayService;

    private final ApplicationEventPublisher applicationEventPublisher;

    private final LockService lockService;

    @Value("${task.receive.way}")
    private Integer receiveWay;


    /**
     * 分页查询
     *
     * @param dto
     * @return
     */
    @Override
    public TableDataInfo<TaskVO> listTaskPage(TaskPageDTO dto) {
        AssertUtil.isNotEmpty(dto.getType(), "帖子类型不能为空");
        // 根据类型通过工厂模式获取策略，执行对应的业务逻辑
        AbstractTaskStrategy strategy = TaskFactory.getStrategyNoNull(dto.getType());
        IPage<TaskVO> taskVOPage = strategy.getTaskVOPage(dto);
        return TableDataInfo.build(taskVOPage);
    }

    /**
     * 获取任务详情
     *
     * @param id
     * @return
     */
    @Override
    public R<TaskVO> getTask(long id) {
        Long uid = LoginUtils.getUserId();
        Task task = taskDao.getById(id);
        TaskVO taskVo = BeanUtil.copyProperties(task, TaskVO.class);
        if (StringUtils.isNotEmpty(task.getImgUrl())) {
            taskVo.setImages(Arrays.asList(task.getImgUrl().split(";")));
        }
        // 查询任务的状态，以及前端按钮的显示情况
        long time1 = System.currentTimeMillis();
        CompletableFutureUtils.createRuns(
                () -> {
                    // 设置是否点赞与收藏和关注
                    setLikedAndCollectedTask(taskVo, uid);
                    // 当任务不是普通贴时，查询任务领取状态
                    if (!TaskTypeEnum.TASK_TYPE_COMMON.getType().equals(task.getType())) {
                        List<TaskReceiveVO> taskReceiveVOS = getTaskReceiveVOS(id, uid, task);
                        taskVo.setTaskReceiveList(taskReceiveVOS);
                    }
                },
                () -> {
                    if (!TaskTypeEnum.TASK_TYPE_COMMON.getType().equals(task.getType())) {
                        // 获取两人坐标距离
                        String key = UserRedisKey.USER_INFO_GEO;
                        String taskUserId = String.valueOf(task.getUserId());
                        taskVo.setDistance(RedisUtils.getGeoEachDistance(key, String.valueOf(uid), taskUserId));
                    }
                }).join();
        long time2 = System.currentTimeMillis();
        System.out.println("总耗时：" + (time2 - time1));
        return R.ok(taskVo);
    }

    /**
     * 创建任务
     *
     * @param dto 实例对象
     * @return
     */
    @Override
    @Transactional
    public R<Object> saveTask(TaskDTO dto) {
        Task task = BeanUtil.copyProperties(dto, Task.class);
        task.setStatus(TaskReceiveStatusEnum.RECEIVE_STATUS_CANCEL.getType());
        if (!TaskTypeEnum.TASK_TYPE_COMMON.getType().equals(dto.getType()) && Objects.isNull(dto.getEndTime())) {
            task.setEndTime(new Date().getTime() + 1000 * TimeConstant.WEEK_TIME);
        }
        User user = LoginUtils.getUser();
        task.setUserId(user.getId()).setUserAvatar(user.getAvatar());
        if (CollUtil.isNotEmpty(dto.getImages())) {
            String images = String.join(";", dto.getImages());
            task.setImgUrl(images);
        }
        // 如果是求助贴直接激活
        if (TaskTypeEnum.TASK_TYPE_HELP.getType().equals(dto.getType())) {
            task.setStatus(TaskReceiveStatusEnum.RECEIVE_STATUS_ING.getType());
        }
        taskDao.save(task);

        // 执行创建非普通贴的数量策略
        if (!TaskTypeEnum.TASK_TYPE_COMMON.getType().equals(dto.getType())) {
            AbstractReceiveStrategy strategy = ReceiveFactory.getStrategy(receiveWay);
            strategy.createTask(task);
        }

        // 发送添加经纬度到redis的事件
        GeoEventPOJO pojo = new GeoEventPOJO()
                .setUid(user.getId())
                .setX(dto.getX())
                .setY(dto.getY());
        applicationEventPublisher.publishEvent(new TaskUserGeoEvent(this, pojo));

        // 如果是赏金贴、征召贴，触发支付页面返回给前端
        if (List.of(TaskTypeEnum.TASK_TYPE_BOUNTY.getType(), TaskTypeEnum.TASK_TYPE_NEAR.getType())
                .contains(dto.getType())) {
            AlipayDto alipayDto = BeanUtil.copyProperties(dto, AlipayDto.class);
            alipayDto.setSubject(task.getTitle()).setId(task.getId());
            String payHtml = alipayService.pay(alipayDto);
            return R.ok(payHtml);
        }
        return R.ok();
    }

    /**
     * 修改任务
     *
     * @param dto 实例对象
     * @return
     */
    @Override
    @Transactional
    public R<Object> updateTask(TaskDTO dto) {
        Task task = BeanUtil.copyProperties(dto, Task.class);
        if (CollUtil.isNotEmpty(dto.getImages())) {
            String images = String.join(";", dto.getImages());
            task.setImgUrl(images);
        }
        taskDao.updateById(task);
        // 发送添加经纬度到redis的事件
        GeoEventPOJO pojo = new GeoEventPOJO()
                .setUid(LoginUtils.getUserId())
                .setX(dto.getX())
                .setY(dto.getY());
        applicationEventPublisher.publishEvent(new TaskUserGeoEvent(this, pojo));
        return R.ok();
    }

    /**
     * 删除任务
     *
     * @param ids 任务id集合
     * @return
     */
    @Override
    public R<Object> deleteTask(List<Long> ids) {
        // 删除任务前，把任务的评论删除
        List<TaskComment> taskComments = taskCommentDao.getBaseMapper()
                .selectList(new LambdaQueryWrapper<TaskComment>().in(TaskComment::getTaskId, ids));
        if (CollUtil.isNotEmpty(taskComments)) {
            taskCommentDao.removeByIds(taskComments.stream().map(TaskComment::getId).collect(Collectors.toList()));
        }
        return R.ok(taskDao.removeByIds(ids));
    }

    /**
     * 任务点赞
     *
     * @param id
     * @return
     */
    @Override
    public boolean likeTask(long id) {
        Task entity = new Task();
        Long userId = LoginUtils.getUserId();
        String key = TaskRedisKey.getKey(TaskRedisKey.TASK_LIKED_SET, id);
        Boolean member = RedisUtils.sIsMember(key, userId);
        BeanUtils.copyProperties(baseMapper.selectById(id), entity);
        return EntityOperations.doUpdate(baseMapper)
                .get(() -> {
                    if (BooleanUtil.isTrue(member)) {
                        // 如果已经点赞
                        entity.setLikedNum(entity.getLikedNum() - 1);
                    } else {
                        entity.setLikedNum(entity.getLikedNum() + 1);
                    }
                    return entity;
                })
                .update(d -> {
                })
                .successHook(thisEntity -> {
                    // 发送任务点赞、取消赞、收藏、取消收藏等操作的事件
                    TaskRedisSetPOJO pojo = new TaskRedisSetPOJO()
                            .setRedisSetTypeEnum(RedisSetTypeEnum.TASK_LIKED)
                            .setKey(id)
                            .setMember(userId)
                            .setTimes(TimeConstant.YEAR_TIME);
                    applicationEventPublisher.publishEvent(new TaskRedisSetEvent(this, pojo));
                })
                .execute().isPresent();
    }

    /**
     * 任务收藏
     *
     * @param id
     * @return
     */
    @Override
    public boolean collectTask(long id) {
        Task entity = new Task();
        Long userId = LoginUtils.getUserId();
        BeanUtils.copyProperties(baseMapper.selectById(id), entity);
        String key = TaskRedisKey.getKey(TaskRedisKey.TASK_COLLECTED_SET, id);
        Boolean member = RedisUtils.sIsMember(key, userId);
        return EntityOperations.doUpdate(baseMapper)
                .get(() -> {
                    if (BooleanUtil.isTrue(member)) {
                        // 如果已经收藏
                        entity.setCollectedNum(entity.getCollectedNum() - 1);
                    } else {
                        entity.setCollectedNum(entity.getCollectedNum() + 1);
                    }
                    return entity;
                })
                .update(d -> {
                })
                .successHook(thisEntity -> {
                    // 发送任务点赞、取消赞、收藏、取消收藏等操作的事件
                    TaskRedisSetPOJO pojo = new TaskRedisSetPOJO()
                            .setRedisSetTypeEnum(RedisSetTypeEnum.TASK_COLLECTED)
                            .setKey(id)
                            .setMember(userId)
                            .setTimes(TimeConstant.YEAR_TIME);
                    applicationEventPublisher.publishEvent(new TaskRedisSetEvent(this, pojo));
                })
                .execute().isPresent();
    }

    /**
     * 修改任务状态
     *
     * @param type      状态类型 0取消任务 1领取任务  2完成任务
     * @param taskId    任务id
     * @param receiveId 领取任务者id
     * @return null
     */
    @Override
    @Transactional
    public R<Object> updateTaskStatus(Integer type, long taskId, long receiveId) {
        Task task = taskDao.getById(taskId);
        // 任务领取策略
        Integer level = task.getLevel() != null ? task.getLevel() : receiveWay;
        // 根据receiveWay选择0、RSemaphore信号量锁 1、lua脚本 2、java乐观锁 3、RLock锁
        AbstractReceiveStrategy strategy = ReceiveFactory.getStrategy(level);
        if (TaskReceiveStatusEnum.RECEIVE_STATUS_CANCEL.getType().equals(type)) {
            // 任务取消
            TaskReceive taskReceive = taskReceiveDao.getByReceiverId(taskId, receiveId);
            taskReceive.setStatus(type);
            taskReceiveDao.updateById(taskReceive);
            strategy.cancelTask(task);
        } else if (TaskReceiveStatusEnum.RECEIVE_STATUS_FINISH.getType().equals(type)) {
            // 任务完成
            TaskReceive taskReceive = taskReceiveDao.getByReceiverId(taskId, receiveId);
            taskReceive.setStatus(type);
            taskReceiveDao.updateById(taskReceive);
        } else if (TaskReceiveStatusEnum.RECEIVE_STATUS_ING.getType().equals(type)) {
            // 任务领取
            AssertUtil.isTrue(TaskReceiveStatusEnum.RECEIVE_STATUS_ING.getType().equals(task.getStatus()), "任务还未激活");
            return strategy.receiveTask(task);
        }
        return R.ok();
    }

    /**
     * 任务领取测试方法
     *
     * @param type      状态类型 0取消任务 1领取任务  2完成任务
     * @param taskId    任务id
     * @param receiveId 领取任务者id
     * @return null
     */
    @Override
    @Transactional
    public R<Object> updateTaskStatus2(Integer type, long taskId, long receiveId) {
        Task task = taskDao.getById(taskId);
        // 任务领取
        AssertUtil.isTrue(TaskReceiveStatusEnum.RECEIVE_STATUS_ING.getType().equals(task.getStatus()), "任务还未激活");
        return receiveTask(task);
    }


    @Override
    public R<List<TaskCopy>> testTask(Integer id) {
        // 设置阈值
        int threshold = 2000000;
        int count = taskCopyDao.count();
        // 当总数超过阈值
        if (count > threshold) {
            int start = id == null ? 0 : id;
            return R.ok(taskCopyDao.taskCopyList(start, start + threshold));
        } else {
            return R.ok(taskCopyDao.taskCopyList(0, count));
        }
    }

    /**
     * 多线程+原子类领取任务测试方法
     *
     * @param task
     * @return
     */
    public R<Object> receiveTask(Task task) {
        long time1 = System.currentTimeMillis();
        String key = TaskRedisKey.getKey("receive:test_%d", task.getId());
        // 已领取任务数量
        Long num = RedisUtils.sGetSetSize(key);
        // 任务数量
        Integer storeNum = task.getBountyNum() != null ? task.getBountyNum() : task.getHelpBountyNum();
        if (num >= storeNum) {
            // 批量插入只会执行一次，锁住，防止多个请求进来批量插入
            // 有任务或没库存 说明已经领完了 要判断两次 第一次判断为了性能
            Integer count1 = taskReceiveDao.getCountByTaskId(task.getId());
            AssertUtil.isTrue(count1 == 0, "任务已经全部领完！");
            lockService.executeWithLock(String.valueOf(task.getId()), 0, TimeUnit.SECONDS, () -> {
                // 有任务或没库存 说明已经领完了 要判断两次 第二次判断为了并发安全
                Integer count2 = taskReceiveDao.getCountByTaskId(task.getId());
                AssertUtil.isTrue(count2 == 0, "任务已经全部领完！");
                // 因为没有加锁的情况下，redis存储的数量大概率是超过赏金设定数量
                // 因此再添加领取者时，通过atomic原子类进行库存扣减，
                AtomicInteger atomic = new AtomicInteger(storeNum);
                List<TaskReceive> list = Collections.synchronizedList(new ArrayList<>());
                Set<String> strings = RedisUtils.sGet(key);
                // 存放多线程并发执行的结果集
                List<CompletableFuture<Void>> completableFutureList = new ArrayList<>();
                assert strings != null;
                for (String info : strings) {
                    // 使用多线程+原子类，快速创建领取信息放入List，以及移除任务超领的用户
                    CompletableFuture<Void> run = CompletableFutureUtils.createRun(() -> {
                        String replaceInfo = info.replace("\"", "");
                        String[] split = replaceInfo.split(",");
                        if (atomic.decrementAndGet() >= 0) {
                            TaskReceive taskReceive = new TaskReceive()
                                    .setTaskId(task.getId())
                                    .setStatus(TaskReceiveStatusEnum.RECEIVE_STATUS_ING.getType())
                                    .setReceiverId(Long.parseLong(split[0]))
                                    .setReceiverName(split[1])
                                    .setReceiveTime(new Date().getTime());
                            list.add(taskReceive);
                        } else {
                            // 如果为0，就把集合多出来用户的移除
                            RedisUtils.lRemove(key, 1, info);
                        }
                    });
                    completableFutureList.add(run);
                }
                // 阻塞多线程，用来获取值
                CompletableFuture.allOf(completableFutureList.toArray(CompletableFuture[]::new)).join();
                // todo 用mq发送给websocket服务，推送给这些在redis集合中的用户一个领取任务成功的提示

                System.out.println("开始批量插入数据库！");
                taskReceiveDao.saveAll(list);
                // 任务降级，有人取消任务，就不能再用这种方式领取任务；
                // 这种是用来处理超大库存量和并发量一抢而空的情况
                task.setLevel(ReceiveTypeEnum.RECEIVE_RLOCK.getType());
                taskDao.updateById(task);
                return R.ok();
            });
        } else {
            // 如果还有库存，将用户uid存入set集合
            User user = LoginUtils.getUser();
            RedisUtils.sSet(key, user.getId() + "," + user.getName());
            long time2 = System.currentTimeMillis();
            System.out.println("抢任务耗时：" + (time2 - time1));
            AssertUtil.isTrue(false, "正在疯狂抢单，请稍后");
        }
        return null;
    }

    /**
     * 设置每条任务的点赞和关注状态方法
     *
     * @param taskVo 任务vo
     */
    public static void setLikedAndCollectedTask(TaskVO taskVo, Long userId) {
        if (userId != null) {
            // 点赞
            String likedKey = TaskRedisKey.getKey(TaskRedisKey.TASK_LIKED_SET, taskVo.getId());
            Boolean likedMember = RedisUtils.sIsMember(likedKey, userId);
            taskVo.setIsLiked(BooleanUtil.isTrue(likedMember));

            // 收藏
            String collectedKey = TaskRedisKey.getKey(TaskRedisKey.TASK_COLLECTED_SET, taskVo.getId());
            Boolean collectedMember = RedisUtils.sIsMember(collectedKey, userId);
            taskVo.setIsCollected(BooleanUtil.isTrue(collectedMember));

            // 判断不是当前登录人发的帖子
            if (!userId.equals(taskVo.getUserId())) {
                // 查询发帖人的粉丝列表是否包含当前登陆人
                String followedKey = UserRedisKey.getKey(UserRedisKey.USER_FOLLOWED_SET, taskVo.getUserId());
                Boolean member = RedisUtils.sIsMember(followedKey, userId);
                if (member) {
                    taskVo.setIsFollow(1);
                } else {
                    taskVo.setIsFollow(0);
                }
            }
        } else {
            taskVo.setIsLiked(false).setIsCollected(false).setIsFollow(0);
        }
    }

    /**
     * 返回领取任务的状态方法
     *
     * @param id   任务id
     * @param task 任务
     * @return
     */
    private List<TaskReceiveVO> getTaskReceiveVOS(long id, Long uid, Task task) {
        List<TaskReceiveVO> taskReceiveVOS = new ArrayList<>();
        // 查询没有被取消、任务进行中或已完成的任务
        List<TaskReceive> taskReceiveList = taskReceiveDao.getGtZero(id);
        // 任务完成情况由 2已完成的任务+1进行中的任务+0待领取的任务 三部分组成
        // 任务查看有三类人：发帖人+任务领取人+未领取人
        if (CollUtil.isNotEmpty(taskReceiveList)) {
            // ①已完成任务：三类人显示按钮的情况是一致的
            taskReceiveList.stream().filter(t -> t.getStatus() > TaskReceiveStatusEnum.RECEIVE_STATUS_ING.getType()).forEach(data -> {
                TaskReceiveVO taskReceiveVO = BeanUtil.copyProperties(data, TaskReceiveVO.class);
                setButtonStatus(taskReceiveVO, taskReceiveVOS,
                        TaskReceiveButtonEnum.RECEIVE_BUTTON_HIDE,
                        TaskReceiveButtonEnum.RECEIVE_BUTTON_HIDE,
                        TaskReceiveButtonEnum.RECEIVE_BUTTON_HIDE);
            });

            // ②进行中任务
            List<TaskReceive> receives = taskReceiveList.stream().filter(t ->
                    t.getStatus().equals(TaskReceiveStatusEnum.RECEIVE_STATUS_ING.getType())).collect(Collectors.toList());
            // 2-2其他领取人和2-4未领取人 不是发帖人就先把其他领取人获取出来
            if (!task.getUserId().equals(uid)) {
                receives.forEach(data -> {
                    if (!data.getReceiverId().equals(uid)) {
                        TaskReceiveVO taskReceiveVO = BeanUtil.copyProperties(data, TaskReceiveVO.class);
                        setButtonStatus(taskReceiveVO, taskReceiveVOS,
                                TaskReceiveButtonEnum.RECEIVE_BUTTON_HIDE,
                                TaskReceiveButtonEnum.RECEIVE_BUTTON_HIDE,
                                TaskReceiveButtonEnum.RECEIVE_BUTTON_HIDE);
                    }
                });
            }

            if (receives.stream().anyMatch(t -> t.getReceiverId().equals(uid))) {
                // 2-1领取人本人
                receives.forEach(data -> {
                    if (data.getReceiverId().equals(uid)) {
                        TaskReceiveVO taskReceiveVO = BeanUtil.copyProperties(data, TaskReceiveVO.class);
                        setButtonStatus(taskReceiveVO, taskReceiveVOS,
                                TaskReceiveButtonEnum.RECEIVE_BUTTON_DISPLAY,
                                TaskReceiveButtonEnum.RECEIVE_BUTTON_HIDE,
                                TaskReceiveButtonEnum.RECEIVE_BUTTON_HIDE);
                    }
                });
            } else if (uid.equals(task.getUserId())) {
                // 2-3发帖人 获取所有正在进行的项目
                receives.forEach(data -> {
                    TaskReceiveVO taskReceiveVO = BeanUtil.copyProperties(data, TaskReceiveVO.class);
                    setButtonStatus(taskReceiveVO, taskReceiveVOS,
                            TaskReceiveButtonEnum.RECEIVE_BUTTON_DISPLAY,
                            TaskReceiveButtonEnum.RECEIVE_BUTTON_DISPLAY,
                            TaskReceiveButtonEnum.RECEIVE_BUTTON_HIDE);
                });
            }

            // ③待领取的任务 未领取人
            if (taskReceiveList.stream().noneMatch(t -> t.getReceiverId().equals(uid))
                    && !task.getUserId().equals(uid)) {
                Integer num = task.getBountyNum() != 0 ? task.getBountyNum() : task.getHelpBountyNum();
                if (taskReceiveList.size() < num) {
                    setButtonStatus(new TaskReceiveVO(), taskReceiveVOS,
                            TaskReceiveButtonEnum.RECEIVE_BUTTON_HIDE,
                            TaskReceiveButtonEnum.RECEIVE_BUTTON_HIDE,
                            TaskReceiveButtonEnum.RECEIVE_BUTTON_DISPLAY);
                }
            }
        } else {
            // ③待领取的任务 未领取人
            if (!uid.equals(task.getUserId())) {
                TaskReceiveVO taskReceiveVO = new TaskReceiveVO();
                setButtonStatus(taskReceiveVO, taskReceiveVOS,
                        TaskReceiveButtonEnum.RECEIVE_BUTTON_HIDE,
                        TaskReceiveButtonEnum.RECEIVE_BUTTON_HIDE,
                        TaskReceiveButtonEnum.RECEIVE_BUTTON_DISPLAY);
            }
        }
        return taskReceiveVOS;
    }

    /**
     * 设置按钮状态
     *
     * @param taskReceiveVO
     * @param statusEnum1   取消按钮
     * @param statusEnum2   完成按钮
     * @param statusEnum3   接收按钮
     */
    private void setButtonStatus(TaskReceiveVO taskReceiveVO, List<TaskReceiveVO> taskReceiveVOS,
                                 TaskReceiveButtonEnum statusEnum1,
                                 TaskReceiveButtonEnum statusEnum2,
                                 TaskReceiveButtonEnum statusEnum3) {
        taskReceiveVO.setCancelBut(statusEnum1.getType())
                .setFinishBut(statusEnum2.getType())
                .setReceiveBut(statusEnum3.getType());
        taskReceiveVOS.add(taskReceiveVO);
    }


    /**
     * 用来测试多线程的代码
     */
    public void myFunction() {
        // 库存数量
        AtomicInteger atomic = new AtomicInteger(101);
        String key = "testKye";
        // 用户集合：
        Set<String> strings = RedisUtils.sGet(key);
        for (String info : strings) {
            CompletableFutureUtils.createRun(() -> {
                // decrementAndGet作用就是原子性的-1，并返回-1后的值
                if (atomic.decrementAndGet() >= 0) {
                    // todo 插入数据库
                } else {
                    // 如果-1后的值小于0，说明没有库存了，就把集合多出来用户的移除
                    System.out.println(info);
                    String replace = info.replace('"', ' ').trim();
                    RedisUtils.sRemove(key, replace);
                }
            });
        }
    }

    public int getSum() {
        int m = 10;
        int n = 20;
        int k = m + n;
        return k;
    }

    public void testNum() {
        int i = getSum();
        int j = 10;
    }
}

